// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.linqingying.gitcode.pullrequest.ui.timeline

import com.intellij.collaboration.ui.CollaborationToolsUIUtil
import com.intellij.collaboration.ui.SimpleHtmlPane
import com.intellij.collaboration.ui.VerticalListPanel
import com.intellij.collaboration.ui.codereview.timeline.StatusMessageType
import com.intellij.collaboration.ui.html.AsyncHtmlImageLoader
import com.intellij.collaboration.ui.setHtmlBody
import com.intellij.openapi.util.NlsSafe
import com.intellij.openapi.util.text.HtmlBuilder
import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.openapi.vcs.changes.ui.CurrentBranchComponent
import com.intellij.ui.ColorUtil
import com.intellij.util.ui.UIUtil
import com.linqingying.gitcode.api.data.GCActor
import com.linqingying.gitcode.api.data.GCLabel
import com.linqingying.gitcode.api.data.GCUser
import com.linqingying.gitcode.api.data.pullrequest.GCGitRefName
import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestRequestedReviewer
import com.linqingying.gitcode.api.data.pullrequest.GCPullRequestState
import com.linqingying.gitcode.api.data.pullrequest.timeline.*
import com.linqingying.gitcode.i18n.GitCodeBundle.message
import com.linqingying.gitcode.pullrequest.ui.timeline.GCPRTimelineItemUIUtil.createDescriptionComponent
import com.linqingying.gitcode.pullrequest.ui.timeline.GCPRTimelineItemUIUtil.createTimelineItem
import com.linqingying.gitcode.ui.avatars.GCAvatarIconsProvider
import org.jetbrains.annotations.Nls
import javax.swing.JComponent

//class GCPRTimelineEventComponentFactoryImpl(
//  private val htmlImageLoader: AsyncHtmlImageLoader,
//  private val avatarIconsProvider: GCAvatarIconsProvider,
//  private val ghostUser: GCUser,
//) : GCPRTimelineEventComponentFactory<GCPRTimelineEvent> {
//
//    private val simpleEventDelegate = SimpleEventComponentFactory()
//    private val stateEventDelegate = StateEventComponentFactory()
//    private val branchEventDelegate = BranchEventComponentFactory()
//    private val complexEventDelegate = ComplexEventComponentFactory()
//
//    override fun createComponent(event: GCPRTimelineEvent): JComponent {
//        return when (event) {
//            is GCPRTimelineEvent.Simple -> simpleEventDelegate.createComponent(event)
//            is GCPRTimelineEvent.State -> stateEventDelegate.createComponent(event)
//            is GCPRTimelineEvent.Branch -> branchEventDelegate.createComponent(event)
//            is GCPRTimelineEvent.Complex -> complexEventDelegate.createComponent(event)
//            else -> throwUnknownType(event)
//        }
//    }
//
//    private fun throwUnknownType(item: GCPRTimelineEvent): Nothing {
//        throw IllegalStateException("""Unknown event type "${item.javaClass.canonicalName}"""")
//    }
//
//    private abstract inner class EventComponentFactory<T : GCPRTimelineEvent> : GCPRTimelineEventComponentFactory<T> {
//        protected fun eventItem(event: GCPRTimelineEvent, detailsText: @Nls String): JComponent {
//            val content = createDescriptionComponent(detailsText)
//            return createTimelineItem(avatarIconsProvider, event.actor ?: ghostUser, event.createdAt, content)
//        }
//
//        protected fun eventItem(
//          event: GCPRTimelineEvent,
//          type: StatusMessageType,
//          detailsText: @Nls String,
//        ): JComponent {
//            val content = createDescriptionComponent(detailsText, type)
//            return createTimelineItem(avatarIconsProvider, event.actor ?: ghostUser, event.createdAt, content)
//        }
//
//        protected fun eventItem(
//          event: GCPRTimelineEvent,
//          titleText: @Nls String,
//          detailsText: @Nls String? = null,
//        ): JComponent {
//            val titlePane = SimpleHtmlPane(customImageLoader = htmlImageLoader).apply {
//                setHtmlBody(titleText)
//            }
//            val content = if (detailsText == null) {
//                titlePane
//            } else {
//                VerticalListPanel(4).apply {
//                    add(titlePane)
//                    add(createDescriptionComponent(detailsText))
//                }
//            }
//            return createTimelineItem(avatarIconsProvider, event.actor ?: ghostUser, event.createdAt, content)
//        }
//    }
//
//    private inner class SimpleEventComponentFactory : EventComponentFactory<GCPRTimelineEvent.Simple>() {
//        override fun createComponent(event: GCPRTimelineEvent.Simple): JComponent {
//            return when (event) {
//                is GCPRAssignedEvent ->
//                    eventItem(event, assigneesText(assigned = listOf(event.user)))
//
//                is GCPRUnassignedEvent ->
//                    eventItem(event, assigneesText(unassigned = listOf(event.user)))
//
//                is GCPRReviewRequestedEvent ->
//                    eventItem(event, reviewersText(added = listOf(event.requestedReviewer)))
//
//                is GCPRReviewUnrequestedEvent ->
//                    eventItem(event, reviewersText(removed = listOf(event.requestedReviewer)))
//
//                is GCPRLabeledEvent ->
//                    eventItem(event, labelsText(added = listOf(event.label)))
//
//                is GCPRUnlabeledEvent ->
//                    eventItem(event, labelsText(removed = listOf(event.label)))
//
//                is GCPRRenamedTitleEvent ->
//                    eventItem(event, renameText(event.previousTitle, event.currentTitle))
//
//                is GCPRTimelineMergedSimpleEvents -> {
//                    val builder = HtmlBuilder()
//                        .appendParagraph(labelsText(event.addedLabels, event.removedLabels))
//                        .appendParagraph(assigneesText(event.assignedPeople, event.unassignedPeople))
//                        .appendParagraph(reviewersText(event.addedReviewers, event.removedReviewers))
//                        .appendParagraph(event.rename?.let { renameText(it.first, it.second) }.orEmpty())
//
//                    eventItem(event, builder.toString())
//                }
//
//                else -> throwUnknownType(event)
//            }
//        }
//
//        private fun assigneesText(
//          assigned: Collection<GCUser> = emptyList(),
//          unassigned: Collection<GCUser> = emptyList(),
//        ): @Nls String {
//            val assignedNames = assigned.takeIf { it.isNotEmpty() }?.joinToString { actorHTML(it).toString() }
//            val unassignedNames = unassigned.takeIf { it.isNotEmpty() }?.joinToString { actorHTML(it).toString() }
//
//            return when {
//                assignedNames != null && unassignedNames != null ->
//                    message("pull.request.timeline.event.assigned.and.unassigned", assignedNames, unassignedNames)
//
//                assignedNames != null ->
//                    message("pull.request.timeline.event.assigned", assignedNames)
//
//                unassignedNames != null ->
//                    message("pull.request.timeline.event.unassigned", unassignedNames)
//
//                else -> ""
//            }
//        }
//
//        private fun reviewersText(
//          added: Collection<GCPullRequestRequestedReviewer?> = emptyList(),
//          removed: Collection<GCPullRequestRequestedReviewer?> = emptyList(),
//        ): @NlsSafe String {
//            val addedLogins =
//                added.takeIf { it.isNotEmpty() }?.joinToString { reviewerHTML(it ?: ghostUser).toString() }
//            val removedLogins =
//                removed.takeIf { it.isNotEmpty() }?.joinToString { reviewerHTML(it ?: ghostUser).toString() }
//
//            return when {
//                addedLogins != null && removedLogins != null ->
//                    message(
//                        "pull.request.timeline.event.requested.review.and.removed.review.request",
//                        addedLogins,
//                        removedLogins
//                    )
//
//                addedLogins != null ->
//                    message("pull.request.timeline.event.requested.review", addedLogins)
//
//                removedLogins != null ->
//                    message("pull.request.timeline.event.removed.review.request", removedLogins)
//
//                else -> ""
//            }
//        }
//
//        private fun labelsText(
//          added: Collection<GCLabel> = emptyList(),
//          removed: Collection<GCLabel> = emptyList(),
//        ): @Nls String {
//            val addedLabels = added.takeIf { it.isNotEmpty() }?.joinToString { labelHTML(it).toString() }
//            val removedLabels = removed.takeIf { it.isNotEmpty() }?.joinToString { labelHTML(it).toString() }
//
//            return when {
//                addedLabels != null && removedLabels != null ->
//                    message("pull.request.timeline.event.labels.added.and.removed", addedLabels, removedLabels)
//
//                addedLabels != null ->
//                    message("pull.request.timeline.event.labels.added", addedLabels)
//
//                removedLabels != null ->
//                    message("pull.request.timeline.event.labels.removed", removedLabels)
//
//                else -> ""
//            }
//        }
//
//        private fun renameText(oldName: String, newName: String): @Nls String =
//            message("pull.request.timeline.renamed", oldName, newName)
//    }
//
//    private inner class StateEventComponentFactory : EventComponentFactory<GCPRTimelineEvent.State>() {
//        override fun createComponent(event: GCPRTimelineEvent.State): JComponent {
//            return when (event.newState) {
//                GCPullRequestState.CLOSED -> {
//                    eventItem(event, StatusMessageType.SECONDARY_INFO, message("pull.request.timeline.closed"))
//                }
//
//                GCPullRequestState.MERGED -> {
//                    val mergeEvent =
//                        (if (event is GCPRTimelineMergedStateEvents) event.lastStateEvent else event) as GCPRMergedEvent
//                    val text = if (mergeEvent.commit != null) {
//                        val commitText =
//                            HtmlChunk.link(mergeEvent.commit.url, mergeEvent.commit.abbreviatedOid).toString()
//                        val ref = branchHTML(mergeEvent.mergeRefName)
//                        message("pull.request.timeline.merged.commit", commitText, ref)
//                    } else message("pull.request.timeline.merged")
//                    eventItem(event, StatusMessageType.SUCCESS, text)
//                }
//
//                GCPullRequestState.OPEN -> {
//                    eventItem(event, message("pull.request.timeline.reopened"))
//                }
//            }
//        }
//    }
//
//    private inner class BranchEventComponentFactory : EventComponentFactory<GCPRTimelineEvent.Branch>() {
//        override fun createComponent(event: GCPRTimelineEvent.Branch): JComponent {
//            return when (event) {
//                is GCPRBaseRefChangedEvent ->
//                    eventItem(event, message("pull.request.timeline.changed.base.branch"))
//
//                is GCPRBaseRefForcePushedEvent ->
//                    eventItem(
//                        event,
//                        message("pull.request.timeline.branch.force.pushed", branchHTML(event.ref) ?: "base")
//                    )
//
//                is GCPRHeadRefForcePushedEvent ->
//                    eventItem(
//                        event,
//                        message("pull.request.timeline.branch.force.pushed", branchHTML(event.ref) ?: "head")
//                    )
//
//                is GCPRHeadRefDeletedEvent ->
//                    eventItem(event, message("pull.request.timeline.branch.deleted", branchHTML(event.headRefName)))
//
//                is GCPRHeadRefRestoredEvent ->
//                    eventItem(event, message("pull.request.timeline.branch.head.restored"))
//
//                else -> throwUnknownType(event)
//            }
//        }
//
//        private fun branchHTML(ref: GCGitRefName?) = ref?.name?.let { branchHTML(it) }
//    }
//
//    private inner class ComplexEventComponentFactory : EventComponentFactory<GCPRTimelineEvent.Complex>() {
//        override fun createComponent(event: GCPRTimelineEvent.Complex): JComponent {
//            return when (event) {
//                is GCPRReviewDismissedEvent -> {
//                    val author = (event.reviewAuthor ?: ghostUser).login
//                    val text = HtmlBuilder()
//                        .append(message("pull.request.timeline.stale.review.dismissed", author))
//                        .apply {
//                            val msg = event.dismissalMessageHTML
//                            if (msg != null) {
//                                append(HtmlChunk.br())
//                                    .appendRaw(msg)
//                            }
//                        }.toString()
//                    eventItem(event, text)
//                }
//
//                is GCPRReadyForReviewEvent ->
//                    eventItem(event, message("pull.request.timeline.marked.as.ready"))
//
//                is GCPRConvertToDraftEvent ->
//                    eventItem(event, message("pull.request.timeline.marked.as.draft"))
//
//                is GCPRCrossReferencedEvent ->
//                    eventItem(event, message("pull.request.timeline.mentioned"), event.source.asReferenceLink())
//
//                is GCPRConnectedEvent ->
//                    eventItem(event, message("pull.request.timeline.connected"), event.subject.asReferenceLink())
//
//                is GCPRDisconnectedEvent ->
//                    eventItem(event, message("pull.request.timeline.disconnected"), event.subject.asReferenceLink())
//
//                else -> throwUnknownType(event)
//            }
//        }
//    }
//
//    companion object {
//        private fun branchHTML(name: @Nls String): HtmlChunk {
//            val foreground = CurrentBranchComponent.TEXT_COLOR
//            val background = CurrentBranchComponent.getBranchPresentationBackground(UIUtil.getListBackground())
//
//            val iconChunk = HtmlChunk
//                .tag("icon-inline")
//                .attr("src", "icons.CollaborationToolsIcons.Review.Branch")
//            return HtmlChunk.span("color: #${ColorUtil.toHex(foreground)}; background: #${ColorUtil.toHex(background)}")
//                .child(HtmlChunk.nbsp())
//                .child(iconChunk)
//                .addText(name)
//                .child(HtmlChunk.nbsp())
//        }
//
//        private fun labelHTML(label: GCLabel): HtmlChunk {
//            val background = CollaborationToolsUIUtil.getLabelBackground(label.color)
//            val foreground = CollaborationToolsUIUtil.getLabelForeground(background)
//
//            return HtmlChunk.span("color: #${ColorUtil.toHex(foreground)}; background: #${ColorUtil.toHex(background)}")
//                .child(HtmlChunk.nbsp())
//                .addText(label.name)
//                .child(HtmlChunk.nbsp())
//        }
//
//        private fun actorHTML(actor: GCActor): HtmlChunk {
//            return HtmlChunk.link(actor.url, actor.getPresentableName())
//        }
//
//        private fun reviewerHTML(reviewer: GCPullRequestRequestedReviewer): HtmlChunk {
//            return HtmlChunk.link(reviewer.url, reviewer.getPresentableName())
//        }
//
//        private fun HtmlBuilder.appendParagraph(text: @Nls String): HtmlBuilder = apply {
//            if (text.isNotEmpty()) {
//                append(HtmlChunk.p().addRaw(text))
//            }
//        }
//
//        private fun GCPRReferencedSubject.asReferenceLink(): @NlsSafe String {
//            return """${title}&nbsp<a href='${url}'>#${number}</a>"""
//        }
//    }
//}
